# _*_ coding:utf-8 _*_
# 开发团队: Mavericks
# 开发人员：Maverick·Ming
# 开发IDE： PyCharm
#   项目名：DouBanSpider
#   文件名：12 应用规则解析内容.py
# 开发时间：2021/4/1 11:06


# 引入所需模块
import re  # 网页解析，获取数据
import urllib.error  # 制定URL，获取网页数据
import urllib.request
from pprint import pprint

from bs4 import BeautifulSoup  # 正则表达式，进行文字匹配


def main():  # 整体工作流程
    print('hello！开始爬取...')
    baseurl = 'https://movie.douban.com/top250?start='
    # 获取数据
    datalist = get_data(baseurl)
    pprint(datalist)  # 测试:查看处理好之后的内容是否正确
    # save_path = 'data/豆瓣电影Top250.xls'


# 影片详情链接的规则
findLink = re.compile(r'<a href="(.*?)">')  # 创建 正则表达式/字符串模式/规则 对象
# 影片的图片
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S)  # re.S忽略标签中的换行符,让换行符包含在解析字符中
# 影片片名
findTitle = re.compile(r'<span class="title">(.*)</span>')  # r字符串原始格式,避免被转义字符干扰
# 影片评分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
# 评价人数
findJudge = re.compile(r'<span>(\d*)人评价</span>')  # /d表示一个数字
# 影片概况
findInq = re.compile(r'<span class="inq">(.*?)</span>')  # 简要的概况应该不会有换行,有再加re.S
# 影片导演年类等基础信息
findBd = re.compile('<p class="">(.*?)</p>', re.S)
# [(.*)贪心匹配][(.*?)惰性匹配]

# 定义爬取并解析数据的函数
def get_data(baseurl):
    datalist = []
    for i in range(0, 10):  # 调用获取页面信息的函数，10次
        url = baseurl + str(i * 25)  # url封装
        html = ask_url(url)  # 保存获取一个网页的源码
        # 2.逐一解析数据, 找到每个电影item以及item里的内容
        soup = BeautifulSoup(html, 'html.parser')  # 传入一个网页html,对其使用html.parser解析器
        # 为了对每个item进行操作,利用for循环
        for item in soup.find_all('div', class_="item"):  # 找正则表达式=div且属性class_是item的所有标签内容
            data = []  # 保存电影的每一个信息
            item = str(item)  # 将item转换为字符串类型,为转换之前是Tag类型,没办法解析

            # 编写好所有规则之后,开始找内容,存内容
            movie_link = re.findall(findLink, item)[0]  # 调用re.findall(利用规则, 在item文档树里解析信息)
            data.append(movie_link)  # 添加链接

            img_src = re.findall(findImgSrc, item)[0]
            data.append(img_src)  # 添加图片

            titles = re.findall(findTitle, item)  # 可能只有一个中文名,没有外国名
            if len(titles) == 2:
                chinese_title = titles[0]
                data.append(chinese_title)  # 添加中文名
                foreign_title = titles[1].replace('/', '')  # 去除无关字符
                foreign_title = foreign_title.replace(u'\xa0', '')  # 去除扩展字符集
                data.append(foreign_title)  # 添加外国名

            else:
                data.append(titles[0])  # 添加中文名
                data.append(' ')  # 外国名留空

            rating = re.findall(findRating, item)[0]
            data.append(rating)  # 添加评分

            judge = re.findall(findJudge, item)[0]
            data.append(judge)  # 添加评论人数

            inq = re.findall(findInq, item)  # 概述[可能没有概述]
            if len(inq) != 0:
                inq = inq[0].replace('。', '')
                data.append(inq)  # 添加概述
            else:
                data.append(' ')  # 没有概述就留空

            bd = re.findall(findBd, item)[0]
            bd = re.sub('<br(\s+)?/>(\s+)?',' ', bd)  # 去掉<br/>
            bd = re.sub('/', ' ', bd)  # 替换/
            # 同样效果 方案一:
            # bd = bd.replace(u'\xa0', ' ')  # 去除\xa0
            # bd = bd.replace(u'\n', '')  # 去除\n
            # # 删除文字前后空格后,传给data
            # data.append(bd.strip(' '))  # 添加基础信息
            # 结果: '导演: 雷德利·斯科特 Ridley Scott主演: 乔什·哈奈特 Josh Hartnett   ... 2001 美国 英国 动作 历史 战争'
            # 同样效果 方案二:
            bd = bd.replace(u'\xa0', ' ')  # 去除\xa0
            # 删除文字前后空格后,传给data
            data.append(bd.strip())  # 添加基础信息
            # 结果: '导演: 雷德利·斯科特 Ridley Scott主演: 乔什·哈奈特 Josh Hartnett   ... 2001 美国 英国 动作 历史 战争'

            # 以上已经把item的信息处理出来存在data了
            datalist.append(data)  # 把处理好的信息放入datalist

    return datalist


# 得到一个指定url的网页信息内容（只获取其中一个页面的爬取，但是需要250/25=10个页面，就需要些循环调用）
def ask_url(url):
    header = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
    }  # head里的变量值User-Agent用户代理,告诉服务器，我们是浏览器访问，不是爬虫
    # 接着将请求对象封装起来
    req = urllib.request.Request(url, headers=header)
    html = ""
    try:
        response = urllib.request.urlopen(req)  # response 对象接受返回的网页信息
        html = response.read().decode('utf-8')  # 将网页信息中的html信息解码给html

    except urllib.error.URLError as e:
        print('获取网页失败')
        if hasattr(e, 'code'):
            print(e.code)
        if hasattr(e, 'reason'):
            print(e.reason)
    finally:
        return html


# 程序入口，确保程序执行的流程
if __name__ == '__main__':  # 当程序被调用执行时, 按照此语句入口的顺序执行程序，不至于乱序调用
    # 调用函数
    main()
    print('Haha! 爬取完成，请查看movie250.html')